/**
 @file sys_usw_common.c

 @date 2011-11-28

 @version v2.0

 This file provides functions which can be used for GB
*/

#include "ctc_qos.h"
#include "ctc_error.h"
#include "ctc_port.h"
#include "ctc_register.h"
#include "ctc_vlan.h"
#include "sal.h"
#include "dal.h"

#include "sys_usw_common.h"
#include "sys_usw_wb_common.h"
#include "usw/include/drv_io.h"
#include "sys_usw_wb_nh.h"
#include "sys_usw_register.h"

#ifdef CTC_MATH_FLOATING
#include <math.h>
#endif

sys_usw_common_master_t* p_usw_com_master[CTC_MAX_LOCAL_CHIP_NUM_PP] = {NULL};
#define SYS_USW_COM_INIT_CHECK(lchip) \
    if (NULL == p_usw_com_master[lchip]){return CTC_E_NOT_INIT;}

extern int32
sys_usw_ftm_query_table_entry_num(uint8 lchip, uint32 table_id, uint32* entry_num);

char*
sys_output_mac(mac_addr_t in_mac)
{
    static char out_mac[20] = {0};

    sal_sprintf(out_mac, "%.2x%.2x.%.2x%.2x.%.2x%.2x", in_mac[0], in_mac[1], in_mac[2], in_mac[3], in_mac[4], in_mac[5]);
    return out_mac;
}

uint8
sys_usw_map_acl_tcam_lkup_type(uint8 lchip, uint8 ctc_lkup_t)
{
    switch(ctc_lkup_t)
    {
        case CTC_ACL_TCAM_LKUP_TYPE_L2:
            return SYS_ACL_TCAM_LKUP_TYPE_L2;
        case CTC_ACL_TCAM_LKUP_TYPE_L2_L3:
            return SYS_ACL_TCAM_LKUP_TYPE_L2_L3;
        case CTC_ACL_TCAM_LKUP_TYPE_L3:
            return SYS_ACL_TCAM_LKUP_TYPE_L3;
        case CTC_ACL_TCAM_LKUP_TYPE_VLAN:
            return SYS_ACL_TCAM_LKUP_TYPE_VLAN;
        case CTC_ACL_TCAM_LKUP_TYPE_L3_EXT:
            return SYS_ACL_TCAM_LKUP_TYPE_L3_EXT;
        case CTC_ACL_TCAM_LKUP_TYPE_L2_L3_EXT:
            return SYS_ACL_TCAM_LKUP_TYPE_L2_L3_EXT;
        case CTC_ACL_TCAM_LKUP_TYPE_CID:
            return SYS_ACL_TCAM_LKUP_TYPE_CID;
        case CTC_ACL_TCAM_LKUP_TYPE_INTERFACE:
            return SYS_ACL_TCAM_LKUP_TYPE_INTERFACE;
        case CTC_ACL_TCAM_LKUP_TYPE_FORWARD:
            return SYS_ACL_TCAM_LKUP_TYPE_FORWARD;
        case CTC_ACL_TCAM_LKUP_TYPE_FORWARD_EXT:
            return SYS_ACL_TCAM_LKUP_TYPE_FORWARD_EXT;
        case CTC_ACL_TCAM_LKUP_TYPE_UDF:
            return SYS_ACL_TCAM_LKUP_TYPE_UDF;
        case CTC_ACL_TCAM_LKUP_TYPE_COPP:
            return SYS_ACL_TCAM_LKUP_TYPE_COPP;
        case CTC_ACL_TCAM_LKUP_TYPE_STK_HDR:
            return SYS_ACL_TCAM_LKUP_TYPE_STK_HDR;
        default:
            return SYS_ACL_TCAM_LKUP_TYPE_NONE;
    }
}

uint8
sys_usw_unmap_acl_tcam_lkup_type(uint8 lchip, uint8 sys_lkup_t)
{
    switch(sys_lkup_t)
    {
        case SYS_ACL_TCAM_LKUP_TYPE_L2:
            return CTC_ACL_TCAM_LKUP_TYPE_L2;
        case SYS_ACL_TCAM_LKUP_TYPE_L2_L3:
            return CTC_ACL_TCAM_LKUP_TYPE_L2_L3;
        case SYS_ACL_TCAM_LKUP_TYPE_L3:
            return  CTC_ACL_TCAM_LKUP_TYPE_L3;
        case SYS_ACL_TCAM_LKUP_TYPE_VLAN:
            return CTC_ACL_TCAM_LKUP_TYPE_VLAN;
        case SYS_ACL_TCAM_LKUP_TYPE_L3_EXT:
            return  CTC_ACL_TCAM_LKUP_TYPE_L3_EXT;
        case SYS_ACL_TCAM_LKUP_TYPE_L2_L3_EXT:
            return CTC_ACL_TCAM_LKUP_TYPE_L2_L3_EXT;
        case SYS_ACL_TCAM_LKUP_TYPE_CID:
            return CTC_ACL_TCAM_LKUP_TYPE_CID;
        case SYS_ACL_TCAM_LKUP_TYPE_INTERFACE:
            return CTC_ACL_TCAM_LKUP_TYPE_INTERFACE;
        case SYS_ACL_TCAM_LKUP_TYPE_FORWARD:
            return CTC_ACL_TCAM_LKUP_TYPE_FORWARD;
        case SYS_ACL_TCAM_LKUP_TYPE_FORWARD_EXT:
            return CTC_ACL_TCAM_LKUP_TYPE_FORWARD_EXT;
        case SYS_ACL_TCAM_LKUP_TYPE_COPP:
            return CTC_ACL_TCAM_LKUP_TYPE_COPP;
        case SYS_ACL_TCAM_LKUP_TYPE_UDF:
            return CTC_ACL_TCAM_LKUP_TYPE_UDF;
        case SYS_ACL_TCAM_LKUP_TYPE_STK_HDR:
            return CTC_ACL_TCAM_LKUP_TYPE_STK_HDR;
        default:
            return CTC_ACL_TCAM_LKUP_TYPE_L2;
    }
}


/* value = division << shift_bits,is_negative = 0,the computed value is slightly larger*/
int32
sys_usw_common_get_compress_near_division_value(uint8 lchip, uint32 value,uint8 division_wide,
                                                                  uint8 shift_bit_wide, uint16* division, uint16* shift_bits, uint8 is_negative)
{
    uint8 i = 0;
    uint32 valuetmp = 0;
    uint32 base = 0;
    uint16 max_division = 0;
    uint16 max_shift_bit = 0;

    CTC_PTR_VALID_CHECK(division);
    CTC_PTR_VALID_CHECK(shift_bits);
    max_division = 1 << division_wide;
    max_shift_bit = 1 << shift_bit_wide;

    for (i = 0; i < max_shift_bit; i++)
    {
        base = (value >> i);

        if (base < max_division)
        {
            *division = base;
            *shift_bits = i;
            valuetmp = base << i;
            if (valuetmp != value)
            {
                break;
            }
            return CTC_E_NONE;
        }
    }

    valuetmp = value / max_division;
    if(0 == valuetmp)
    {
        *division = value;
        *shift_bits = 0;
        return CTC_E_NONE;
    }

    for (i = 1; i < max_shift_bit; i++)
    {
        if ((valuetmp >= (1 << (i - 1))) && (valuetmp <= ((1 << i)- 1)))
        {
            if(0 == is_negative)
            {
                if ((value + ((1 << i) - 1)) / (1 << i) >= max_division)
                {
                    i++;
                }

                *shift_bits = i;
                *division = (value + ((1 << i) - 1)) / (1 << i);
            }
            else
            {
                if (value  / (1 << i) >= max_division)
                {
                    i++;
                }

                *shift_bits = i;
                *division = value / (1 << i);
            }
            return CTC_E_NONE;
        }
    }

    return CTC_E_INVALID_PARAM;

}

extern uint32
sys_usw_global_get_chip_capability(uint8 lchip, ctc_global_capability_type_t type);

uint32
sys_usw_common_get_vport_num(uint8 lchip)
{
    return MCHIP_CAP(SYS_CAP_SPEC_LOGIC_PORT_NUM);
}

const char*
sys_usw_get_pkt_type_desc(uint8 pkt_type)
{
    switch(pkt_type)
    {
        case CTC_PARSER_PKT_TYPE_ETHERNET:
            return "ETHERNET";
        case CTC_PARSER_PKT_TYPE_IP_OR_IPV6:
            return "IP/IPv4";
        case CTC_PARSER_PKT_TYPE_MPLS:
            return "MPLS";
        case CTC_PARSER_PKT_TYPE_IPV6:
            return "IPV6";
        case CTC_PARSER_PKT_TYPE_MCAST_MPLS:
            return "MCAST_MPLS";
        case CTC_PARSER_PKT_TYPE_CESOETH:
            return "CESOETH";
        case CTC_PARSER_PKT_TYPE_FLEXIBLE:
            return "FLEXIBLE";
        case CTC_PARSER_PKT_TYPE_RESERVED:
            return "RESERVED";
        default:
            return "Error type";
    }

}

int32
sys_usw_dword_reverse_copy(uint32* dest, uint32* src, uint32 len)
{
    uint32 i = 0;
    for (i = 0; i < len; i++)
    {
        *(dest + i) = *(src + (len - i - 1));
    }
    return 0;
}

int32
sys_usw_byte_reverse_copy(uint8* dest, uint8* src, uint32 len)
{
    uint32 i = 0;
    for (i = 0; i < len; i++)
    {
        *(dest + i) = *(src + (len - 1 - i));
    }
    return 0;
}

int32
sys_usw_swap32(uint32* data, int32 len, uint32 hton)
{
    int32 cnt = 0;

    for (cnt = 0; cnt < len; cnt++)
    {
        if (hton)
        {
            data[cnt] = sal_htonl(data[cnt]);
        }
        else
        {
            data[cnt] = sal_ntohl(data[cnt]);
        }
    }

    return CTC_E_NONE;
}

int32
sys_usw_task_create(uint8 lchip,
                                sal_task_t** ptask,
                                char* name,
                                size_t stack_size,
                                int32 prio,
                                sal_task_type_t task_type,
                                unsigned long long cpu_mask,
                                void (* start)(void*),
                                void* arg)
{
    int32 ret = 0;
    sal_task_t tmp_task;

    sal_memset(&tmp_task, 0, sizeof(sal_task_t));
    tmp_task.cpu_mask = cpu_mask;
    tmp_task.task_type = task_type;
    sal_sprintf(tmp_task.name, "%s-%d", name, lchip);

    ret = sal_task_create(ptask, tmp_task.name,stack_size, prio, start, arg);

    return ret;
}

int32
sys_usw_ma_clear_write_cache(uint8 lchip)
{
    uint32 cmd = 0;
    DsMaName_m ds_ma_name;
    uint8  trigger_timer = 0;
    uint32 ma_name_entry_num = 0;
    uint8  rsv_maname_idx = 0;

    if (!DRV_IS_DUET2(lchip))
    {
        return CTC_E_NONE;
    }

    sys_usw_ftm_query_table_entry_num(lchip, DsMaName_t,  &ma_name_entry_num);
    if (!ma_name_entry_num)
    {
        return CTC_E_NONE;
    }

    rsv_maname_idx = ma_name_entry_num - 1;
    cmd = DRV_IOW(DsMaName_t, DRV_ENTRY_FLAG);
    sal_memset(&ds_ma_name, 0xff, sizeof(ds_ma_name));
    for (trigger_timer = 0; trigger_timer < 8; trigger_timer++)
    {
        DRV_IOCTL(lchip, rsv_maname_idx, cmd, &ds_ma_name);
    }
    return CTC_E_NONE;
}

int32
sys_usw_ma_add_to_asic(uint8 lchip, uint32 ma_index, void* dsma)
{
    uint32 cmd = 0;

    cmd = DRV_IOW(DsMa_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, ma_index, cmd, dsma));
    sys_usw_ma_clear_write_cache(lchip);
    return CTC_E_NONE;
}

uint8
sys_usw_l4_user_type_map(uint8 lchip, uint8 type, uint8 is_ctc2drv)
{
    uint8 l4_user_type = type;

    if (is_ctc2drv)
    {
        if (type == CTC_PARSER_L4_USER_TYPE_UDP_VXLAN)
        {
            l4_user_type = DRV_ENUM(DRV_PARSER_L4_USER_TYPE_UDP_VXLAN);
        }
    }
    else
    {
        if (type == DRV_ENUM(DRV_PARSER_L4_USER_TYPE_UDP_VXLAN))
        {
            l4_user_type = CTC_PARSER_L4_USER_TYPE_UDP_VXLAN;
        }
    }
    return l4_user_type;
}

uint8
sys_usw_l4_type_map(uint8 lchip, uint8 type, uint8 is_ctc2drv)
{
    uint8 l4_type = type;

    if (is_ctc2drv)
    {
        if (type == CTC_PARSER_L4_TYPE_UDP)
        {
            l4_type = DRV_ENUM(DRV_PARSER_L4_TYPE_UDP);
        }
        else if (type == CTC_PARSER_L4_TYPE_GRE)
        {
            l4_type = DRV_ENUM(DRV_PARSER_L4_TYPE_GRE);
        }
    }
    else
    {
        if (type == DRV_ENUM(DRV_PARSER_L4_TYPE_UDP))
        {
            l4_type = CTC_PARSER_L4_TYPE_UDP;
        }
        else if (type == DRV_ENUM(DRV_PARSER_L4_TYPE_GRE))
        {
            l4_type = CTC_PARSER_L4_TYPE_GRE;
        }
    }
    return l4_type;
}

char*
sys_output_ipv4(uint32 in_ip)
{
    static  char out_ip4[CTC_IPV6_ADDR_STR_LEN];

    uint32 tempip = sal_ntohl(in_ip);
    sal_inet_ntop(AF_INET, &tempip, out_ip4, CTC_IPV6_ADDR_STR_LEN);

    return out_ip4;
}

void*
sys_usw_com_lookup_entry_hash(uint8 lchip, void* p_hash, uint32 entry_id)
{
    sys_com_entry_hash_t* p_node = NULL;
    if (MCHIP_MISC(lchip)->com_lookup_entry_hash && p_hash)
    {
        p_node = MCHIP_MISC(lchip)->com_lookup_entry_hash(p_hash, entry_id);
    }
    return p_node;
}
int32
sys_usw_com_add_entry_hash(uint8 lchip, uint32 mem_mode, void* p_hash, uint32 entry_id, uint16 pp_bmp)
{
    int32 ret = 0;
    if (MCHIP_MISC(lchip)->com_add_entry_hash && p_hash)
    {
        ret = MCHIP_MISC(lchip)->com_add_entry_hash(lchip, mem_mode, p_hash, entry_id, pp_bmp);
    }
    return ret;
}

int32
sys_usw_com_remove_entry_hash(uint8 lchip, void* p_hash, sys_com_entry_hash_t* p_node)
{
    int32 ret = 0;
    if (MCHIP_MISC(lchip)->com_remove_entry_hash && p_hash)
    {
        ret = MCHIP_MISC(lchip)->com_remove_entry_hash(lchip, p_hash, p_node);
    }
    return ret;
}

int32
sys_usw_com_remove_entry_hash_by_entry_id(uint8 lchip, void* p_hash, uint32 entry_id)
{
    int32 ret = 0;
    if (MCHIP_MISC(lchip)->com_remove_entry_hash_by_entry_id && p_hash)
    {
        ret = MCHIP_MISC(lchip)->com_remove_entry_hash_by_entry_id(lchip, p_hash, entry_id);
    }
    return ret;
}

void*
sys_usw_com_entry_hash_init(uint8 lchip, uint32 entry_num, uint32 block_size)
{
    void* node = NULL;
    if (MCHIP_MISC(lchip)->com_entry_hash_init)
    {
        node = MCHIP_MISC(lchip)->com_entry_hash_init(lchip, entry_num, block_size);
    }
    return node;
}

int32
sys_usw_com_entry_hash_deinit(uint8 lchip, void* user_data)
{
    int32 ret = 0;
    if (MCHIP_MISC(lchip)->com_entry_hash_deinit)
    {
        ret = MCHIP_MISC(lchip)->com_entry_hash_deinit(lchip, user_data);
    }
    return ret;
}

void
sys_usw_com_wb_restore_entry_hash(uint8 lchip, uint32 entry_id, uint32 mode, void* p_hash)
{
    uint8 pp_bmp = 0;
    uint8 pp_base = 0;
    sys_com_entry_hash_t* p_node = NULL;

    if(p_hash == NULL)
    {
        return;
    }
    pp_base = drv_vchip_get_pp_base(lchip);
    CTC_BIT_SET(pp_bmp, lchip - pp_base);


    p_node = sys_usw_com_lookup_entry_hash(0, p_hash, entry_id);
    if(!p_node)
    {
        sys_usw_com_add_entry_hash(lchip, mode, p_hash, entry_id, pp_bmp);
    }
    else
    {
        CTC_BIT_SET(p_node->pp_bmp,lchip - pp_base);
    }

    return;
}


char*
sys_output_ipv6(uint32* in_ip)
{
    static  char out_ip6[CTC_IPV6_ADDR_STR_LEN];

    uint32 ipv6_address[4] = {0, 0, 0, 0};
    ipv6_address[0] = sal_ntohl(in_ip[0]);
    ipv6_address[1] = sal_ntohl(in_ip[1]);
    ipv6_address[2] = sal_ntohl(in_ip[2]);
    ipv6_address[3] = sal_ntohl(in_ip[3]);
    sal_inet_ntop(AF_INET6, ipv6_address, out_ip6, CTC_IPV6_ADDR_STR_LEN);

    return out_ip6;
}

int32
sys_usw_common_register_cb(uint8 lchip, sys_common_cb_type_t type, void* cb)
{
    SYS_USW_COM_INIT_CHECK(lchip);
    CTC_MAX_VALUE_CHECK(type, SYS_CB_MAX_TYPE-1);
    p_usw_com_master[lchip]->p_cb[type] = cb;
    return CTC_E_NONE;
}

int32
sys_usw_common_init(uint8 lchip)
{
    if (p_usw_com_master[lchip])
    {
        return CTC_E_NONE;
    }
    SYS_VCHIP_MASTER_INIT(lchip, p_usw_com_master, CTC_FEATURE_CHIP);
    p_usw_com_master[lchip] = mem_malloc(MEM_SYSTEM_MODULE, sizeof(sys_usw_common_master_t));
    if (NULL == p_usw_com_master[lchip])
    {
        return CTC_E_NO_MEMORY;
    }
    sal_memset(p_usw_com_master[lchip], 0, sizeof(sys_usw_common_master_t));

    dal_get_chip_dev_id(SYS_MAP_LDEV(lchip), &p_usw_com_master[lchip]->dev_id);

    CTC_ERROR_RETURN(sal_mutex_create(&p_usw_com_master[lchip]->pdu_mutex));
    if(p_usw_com_master[lchip]->pdu_mutex == NULL)
    {
        return CTC_E_NO_MEMORY;
    }

    return CTC_E_NONE;
}

int32
sys_usw_common_deinit(uint8 lchip)
{
    if (NULL == p_usw_com_master[lchip])
    {
        return CTC_E_NONE;
    }
    SYS_VCHIP_MASTER_DEINIT(lchip, p_usw_com_master, CTC_FEATURE_CHIP);
    sal_mutex_destroy(p_usw_com_master[lchip]->pdu_mutex);
    mem_free(p_usw_com_master[lchip]);
    return CTC_E_NONE;
}

uint32
sys_usw_is_network_port(uint8 lchip, uint32 gport)
{
    uint32 val = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    dmps_port_info.gport = gport;
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_PORT_TYPE, (void*)&val));
    return val;
}

 int32 sys_usw_ptp_get_rtc_id(uint8 ts_rc)
{
	uint8 ptp_domain[SYS_PTP_TS_RC_MAX]={
		SYS_PTP_RTC_0,//DMA
		SYS_PTP_RTC_1,
		SYS_PTP_RTC_2,
		SYS_PTP_RTC_3,
		
		SYS_PTP_RTC_0,//Top
		SYS_PTP_RTC_1,
		SYS_PTP_RTC_2,
		SYS_PTP_RTC_3,
		SYS_PTP_RTC_4,
		
		SYS_PTP_RTC_0,//Mac
		SYS_PTP_RTC_1,
		SYS_PTP_RTC_2,
		SYS_PTP_RTC_3,	
		SYS_PTP_RTC_0,
		SYS_PTP_RTC_1,
		SYS_PTP_RTC_2,
		SYS_PTP_RTC_3, 
		SYS_PTP_RTC_0,
		SYS_PTP_RTC_1,
		SYS_PTP_RTC_2,
		SYS_PTP_RTC_3,
		SYS_PTP_RTC_0,
		SYS_PTP_RTC_1,
		SYS_PTP_RTC_2,
		SYS_PTP_RTC_3,
		SYS_PTP_RTC_0,
		SYS_PTP_RTC_1,
		SYS_PTP_RTC_2,
		SYS_PTP_RTC_3,
		SYS_PTP_RTC_0,//Mac
		SYS_PTP_RTC_1,
		SYS_PTP_RTC_2,
		SYS_PTP_RTC_3,	
		SYS_PTP_RTC_0,
		SYS_PTP_RTC_1,
		SYS_PTP_RTC_2,
		SYS_PTP_RTC_3, 
		SYS_PTP_RTC_0,
		SYS_PTP_RTC_1,
		SYS_PTP_RTC_2,
		SYS_PTP_RTC_3,
		SYS_PTP_RTC_0,
		SYS_PTP_RTC_1,
		SYS_PTP_RTC_2,
		SYS_PTP_RTC_3,
		SYS_PTP_RTC_0,
		SYS_PTP_RTC_1,
		SYS_PTP_RTC_2,
		SYS_PTP_RTC_3,
		SYS_PTP_RTC_0,//Mac
		SYS_PTP_RTC_1,
		SYS_PTP_RTC_2,
		SYS_PTP_RTC_3,	
		SYS_PTP_RTC_0,
		SYS_PTP_RTC_1,
		SYS_PTP_RTC_2,
		SYS_PTP_RTC_3, 
		SYS_PTP_RTC_0,
		SYS_PTP_RTC_1,
		SYS_PTP_RTC_2,
		SYS_PTP_RTC_3,
		SYS_PTP_RTC_0,
		SYS_PTP_RTC_1,
		SYS_PTP_RTC_2,
		SYS_PTP_RTC_3,
		SYS_PTP_RTC_0,
		SYS_PTP_RTC_1,
		SYS_PTP_RTC_2,
		SYS_PTP_RTC_3,
		SYS_PTP_RTC_0,//Mac
		SYS_PTP_RTC_1,
		SYS_PTP_RTC_2,
		SYS_PTP_RTC_3,	
		SYS_PTP_RTC_0,
		SYS_PTP_RTC_1,
		SYS_PTP_RTC_2,
		SYS_PTP_RTC_3, 
		SYS_PTP_RTC_0,
		SYS_PTP_RTC_1,
		SYS_PTP_RTC_2,
		SYS_PTP_RTC_3,
		SYS_PTP_RTC_0,
		SYS_PTP_RTC_1,
		SYS_PTP_RTC_2,
		SYS_PTP_RTC_3,
		SYS_PTP_RTC_0,
		SYS_PTP_RTC_1,
		SYS_PTP_RTC_2,
		SYS_PTP_RTC_3,
	
		SYS_PTP_RTC_0,//OAM
		SYS_PTP_RTC_1,
		SYS_PTP_RTC_2,
		SYS_PTP_RTC_3,
	
		SYS_PTP_RTC_5,//Meter
	
		SYS_PTP_RTC_0,//IPE
		SYS_PTP_RTC_1,
		SYS_PTP_RTC_2,
		SYS_PTP_RTC_3,
	
		SYS_PTP_RTC_4,//IPE Ipfix
		
		SYS_PTP_RTC_0,//EPE
		SYS_PTP_RTC_1,
		SYS_PTP_RTC_2,
		SYS_PTP_RTC_3,
	
		SYS_PTP_RTC_4,//EPE Ipfix	
		};
    return ptp_domain[ts_rc];
}

int32
sys_usw_ldp_hash_make(sys_com_ldp_node_t* p_data)
{
    return ctc_hash_caculate(sizeof(uint32), p_data);
}

bool
sys_usw_ldp_hash_cmp(sys_com_ldp_node_t* p_data0, sys_com_ldp_node_t* p_data1)
{
    if (!p_data0 || !p_data1)
    {
        return TRUE;
    }

    if (p_data0->ldp == p_data1->ldp)
    {
        return TRUE;
    }

    return FALSE;
}
int32
sys_usw_add_ldp_node(uint8 lchip, ctc_hash_t* p_hash, uint32 ldp, ctc_list_pointer_node_t* list_node)
{
    sys_com_ldp_node_t ldp_node;
    sys_com_ldp_node_t* p_ldp_node = NULL;

    if(NULL == p_hash)
    {
        return CTC_E_NONE;
    }
    ldp_node.ldp = ldp;
    p_ldp_node = ctc_hash_lookup(p_hash, &ldp_node);
    if (NULL == p_ldp_node)
    {
        p_ldp_node = mem_malloc(MEM_SYSTEM_MODULE, sizeof(sys_com_ldp_node_t));
        if(NULL == p_ldp_node)
        {
            return CTC_E_NO_MEMORY;
        }
        p_ldp_node->ldp = ldp;
        if(NULL == ctc_hash_insert(p_hash, p_ldp_node))
        {
            mem_free(p_ldp_node);
            return CTC_E_NO_MEMORY;
        }
        ctc_list_pointer_init(&p_ldp_node->update_list);
    }
    ctc_list_pointer_insert_tail(&p_ldp_node->update_list, list_node);
    return CTC_E_NONE;
}

int32
sys_usw_remove_ldp_node(uint8 lchip, ctc_hash_t* p_hash, uint32 ldp, ctc_list_pointer_node_t* list_node)
{
    sys_com_ldp_node_t ldp_node;
    sys_com_ldp_node_t* p_ldp_node = NULL;

    if(NULL == p_hash)
    {
        return CTC_E_NONE;
    }
    ldp_node.ldp = ldp;
    p_ldp_node = ctc_hash_lookup(p_hash, &ldp_node);
    if (NULL == p_ldp_node)
    {
        return CTC_E_NONE;
    }

    ctc_list_pointer_delete(&p_ldp_node->update_list, list_node);
    list_node->p_next = NULL;
    list_node->p_prev = NULL;
    if(0 == p_ldp_node->update_list.count)
    {
        ctc_hash_remove(p_hash, p_ldp_node);
        mem_free(p_ldp_node);
    }
    return CTC_E_NONE;
}
int32
sys_usw_free_ldp_node(void* node_data, void* user_data)
{
    if (node_data)
    {
        mem_free(node_data);
    }
    return CTC_E_NONE;
}

int32
sys_usw_update_trunkid_by_rchip(uint8 lchip, uint8 remote_gchip, uint8 trunk_id)
{
    
    SYS_CB(SYS_CB_MIRROR_UPDATE_TRUNK_BY_RCHIP, lchip, remote_gchip, trunk_id);    
    SYS_CB(SYS_CB_QOS_UPDATE_TRUNK_BY_RCHIP, lchip, remote_gchip, trunk_id);
    
    return CTC_E_NONE;
}

int32
sys_usw_common_check_port_status(uint8 lchip, uint32 gport, sys_qos_shape_profile_t* shp_profile)
{
    uint32 depth = 0;
    uint32 index = 0;

    /*1.1. check queue flush clear*/
    CTC_ERROR_RETURN(sys_usw_queue_get_port_depth(lchip, gport, &depth));
    do{
        sal_task_sleep(10);
        if((index++) >500)
        {
            return CTC_E_HW_TIME_OUT;
        }
        CTC_ERROR_RETURN(sys_usw_queue_get_port_depth(lchip, gport, &depth));
    }while (depth);

    return CTC_E_NONE;
}

